#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#include "set.h"
#include "set_errno.h"
#include "link.h"

struct set {struct link lnk;};

struct set* set__empty()
{
  struct set* tmp = malloc(sizeof(struct set));
  assert(tmp!=NULL);
  tmp->lnk = lnk__empty();

  return tmp;
}


size_t set__size(const struct set* s)
{
  assert(s!=NULL);

  struct lelement* c = s->lnk.head;
  int i;
  for(i=0; !lnk__is_end(&s->lnk, c); i++)
    c = c->next;

  return i;
}


int set__add(struct set* s, char c)
{
    assert(s!=NULL);

    if(set__find(s,c))
    {
      set__errno = SET__ELEMENT_DUPLICATION;
      return 1;
    }

    struct lelement* e = malloc(sizeof(struct lelement));
    if(e==NULL)
    {
      fprintf(stderr, "set__add(): %s",strerror(errno));
    }

    e->data = c;
    lnk__add_head(&s->lnk, e);

    return 0;
}

int set__remove(struct set* s, char c)
{
  assert(s!=NULL);

  struct lelement* b = s->lnk.head;
  struct lelement* n;
  if(!set__is_empty(s))
  {
    if(b->data == c)
    {
      n = s->lnk.head;
      lnk__remove_head(&s->lnk);
      free(n);
      return 0;
    }
    while(!lnk__is_end(&s->lnk,b->next))
    {
      if(b->next->data == c)
      {
        n= b->next;
        lnk__remove_after(&s->lnk, b);
        free(n);
        return 0;
      }
      b = b->next;
    }
  }

  set__errno = SET__ELEMENT_UNKNOWN;
  return 1;
}

int set__is_empty(const struct set* s)
{
   assert(s!=NULL);

  return lnk__is_end(&s->lnk, s->lnk.head);
}


int set__find(const struct set* s, char c)
{
  assert(s!=NULL);

  struct lelement* b = s->lnk.head;
  while(!lnk__is_end(&s->lnk, b))
  {
    if(b->data == c)
      return 1;
    b = b->next;
  }

  return 0;
}

int set__inter(const struct set * s1, const struct set * s2, struct set * si)
{
  assert(s1 != NULL);
  assert(s2 != NULL);
  assert(set__is_empty(si));

  int err = 0;

  struct lelement* b = s1->lnk.head;
  while(!lnk__is_end(&s1->lnk, b))
  {
    if(set__find(s2, b->data))
      set__add(si,b->data);
    b = b->next;
  }

  return !err;
}

int set__union(const struct set * s1, const struct set * s2, struct set * su)
{
  assert(s1 != NULL);
  assert(s2 != NULL);
  assert(set__is_empty(su));

  int err = 0;

  set__copy(s2, su);

  struct lelement* b = s1->lnk.head;
  while(!lnk__is_end(&s1->lnk, b))
  {
    err |= set__add(su,b->data);
    b = b->next;
  }

  return !err;
}

int set__copy(const struct set* si, struct set* so)
{
  assert(set__is_empty(so));
  struct lelement* b = si->lnk.head;
  while(!lnk__is_end(&si->lnk, b))
  {
    set__add(so, b->data);

    b = b->next;
  }

  return 0;
}

int set__compare(const struct set * s1, const struct set * s2)
{
  struct lelement* b = s1->lnk.head;
  while(!lnk__is_end(&s1->lnk, b))
  {
    if(!set__find(s2,b->data))
      return 0;
    b = b->next;
  }
  return 1;
}

void set__free(struct set* s)
{
  assert(s!=NULL);

  struct lelement* c = s->lnk.head;
  struct lelement* n;

  while(!lnk__is_end(&s->lnk,c))
  {
    n = c->next;
    free(c);
    c = n;
  }

  free(s);
}
























